﻿using Microsoft.Extensions.Configuration;
using Shop.Core.Consts;
using Shop.Core.Helper;
using Shop.Core.Redis;
using Shop.Core.Repository;
using Shop.Core.Share;
using Shop.Core.WeChat;
using Shop.IServices;
using Shop.Model.Dto.Common;
using Shop.Model.Dto.User;
using Shop.Model.Entity.Use;
using Shop.Model.View.Use;

namespace Shop.Services
{
    public class UserAppService : IUserAppService
    {
        private RepositoryBase<UseUser> _userRepository;

        private RepositoryBase<UseUserRelation> _userRelationRepository;

        private readonly WeChatService _weChatService;

        private readonly IAliyunAppService _aliyunAppService;

        private readonly IRedisProvider _redisProvider;

        private readonly IUserContext _userContext;

        private readonly IConfiguration _config;

        public UserAppService(RepositoryBase<UseUser> userRepository
            , RepositoryBase<UseUserRelation> userRelationRepository
            , WeChatService weChatService
            , IAliyunAppService aliyunAppService
            , IRedisProvider redisProvider
            , IUserContext userContext
            , IConfiguration config)
        {
            _userRepository = userRepository;
            _userRelationRepository = userRelationRepository;
            _weChatService = weChatService;
            _aliyunAppService = aliyunAppService;
            _redisProvider = redisProvider;
            _userContext = userContext;
            _config = config;
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <returns></returns>
        public async Task<UserInforVo> GetUserBaseInfor()
        {
            var userinfo = await _userRepository.GetFirstAsync(x => x.Id == _userContext.Id &&  !string.IsNullOrWhiteSpace(x.Tele));
            if (userinfo == null)
                return new UserInforVo() { Id = _userContext.Id};
            else
            {
                var result = new UserInforVo()
                {
                    Id = userinfo.Id,
                    Nickname = userinfo.Nickname,
                    Head = userinfo.Head,
                    Code = userinfo.Code,
                    Sex = userinfo.Sex,
                    Tele = userinfo.Tele,
                    Grade = userinfo.Grade,
                    SignContract = userinfo.Audit == 1
                };
                //上级检测
                _ = bool.TryParse(_config["Shop:CheckSuperior"], out bool check);
                if (check)
                    result.Superior = userinfo.SuperiorUser != ShopConst.DefaultSuperior;
                return result;
            }
        }

        /// <summary>
        /// 用户添加上级
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<bool> AddSuperior(int input)
        {
            var user = await _userRepository.GetByIdAsync(_userContext.Id);
            if(user.SuperiorUser != ShopConst.DefaultSuperior)
                return true;
            var super = await _userRepository.GetFirstAsync(x => x.Code == input && !string.IsNullOrEmpty(x.UnionId) && x.State != -1);
            if (super == null)
                throw new Exception("上级不存在！");
            user.SuperiorUser = super.Id;

            //用户所有下级
            var ancestor = await _userRelationRepository.Where(x => x.Ancestor == user.Id).ToListAsync();
            //上级的所有上级
            var subRelation = await _userRelationRepository.Where(c => c.Descendant == super.Id).ToListAsync();
            subRelation.Add(new UseUserRelation { Ancestor = super.Id, Level = 0 });

            List<UseUserRelation> userRelations = new();
            foreach (var relation in subRelation)
            {
                userRelations.Add(new UseUserRelation
                {
                    Id = IdGenerater.GetNextId(),
                    Ancestor = relation.Ancestor,
                    Descendant = user.Id,
                    Level = relation.Level + 1,
                    CreateTime = DateTime.Now
                });
                foreach (var item in ancestor)
                {
                    userRelations.Add(new UseUserRelation
                    {
                        Id = IdGenerater.GetNextId(),
                        Ancestor = relation.Ancestor,
                        Descendant = item.Descendant,
                        Level = relation.Level + item.Level + 1,
                        CreateTime = DateTime.Now
                    });
                }
            }

            var ids = ancestor.Select(x => x.Descendant).ToList();
            ids.Add(user.Id);
            try
            {
                _userRepository.BeginTran();
                await _userRepository.Change<UseUserRelation>().DeleteAsync(x => ids.Contains(x.Descendant) && x.Ancestor == ShopConst.DefaultSuperior);
                await _userRepository.Change<UseUserRelation>().InsertRangeAsync(userRelations);
                await _userRepository.UpdateAsync(user);
                _userRepository.CommitTran();
            }catch (Exception)
            {
                _userRepository.RollbackTran();
                return false;
            }
            return true;
        }

        /// <summary>
        /// 发送修改验证码
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<AppResult> SendChangeCode()
        {
            var user = await _userRepository.GetByIdAsync(_userContext.Id);
            var data = await _redisProvider.StringGetAsync("cr" + user.Id);
            if (string.IsNullOrEmpty(data))
            {
                Random rad = new();
                int code = rad.Next(1000, 10000);
                string smsCodeTemp = "{\"code\":\"" + code + "\"}";
                _ = await _redisProvider.StringSetAsync("cc" + user.Id, code.ToString(), new TimeSpan(0, 5, 0));
                _ = await _redisProvider.StringSetAsync("cr" + user.Id, "1", new TimeSpan(0, 1, 0));
                return await _aliyunAppService.SendSms(new SendSmsDto
                {
                    Tel = user.Tele,
                    Temp = "SMS_265650303",
                    TempParam = smsCodeTemp
                });
            }
            else
                return new AppResult(400, " 请不要频繁发送短信");
        }

        /// <summary>
        /// 检查修改验证码是否正确
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<bool> CheckChangeCode(string input)
        {
            var code = await _redisProvider.StringGetAsync("cc" + _userContext.Id);
            if (input != code)
                return false;
            await _redisProvider.KeyDelAsync("cc" + _userContext.Id);
            await _redisProvider.KeyDelAsync("cr" + _userContext.Id);
            return true;
        }

        /// <summary>
        /// 修改交易密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<bool> ChangeTradePassword(string input)
        {
            var user = await _userRepository.GetByIdAsync(_userContext.Id);
            user.WithdrawalPassword = CommonHelper.Md5For32(input);
            return await _userRepository.UpdateAsync(user);
        }

        /// <summary>
        /// 修改登录密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<bool> ChangePassword(string input)
        {
            var user = await _userRepository.GetByIdAsync(_userContext.Id);
            user.PassWord = CommonHelper.Md5For32(input);
            return await _userRepository.UpdateAsync(user);
        }

        /// <summary>
        /// 检查交易密码是否正确
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<bool> VerifyTradePassworde()
        {
            var user = await _userRepository.GetByIdAsync(_userContext.Id);
            return !string.IsNullOrEmpty(user.WithdrawalPassword);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<bool> ChangeTelephone(string input)
        {
            var user = await _userRepository.GetByIdAsync(_userContext.Id);
            //新的手机号不能和旧的手机号相同
            if (user.Tele.Equals(input))
                throw new Exception("请输入新的手机号码!");
            var exit = await _userRepository.AnyAsync(x => x.Tele.Equals(input) && x.State != -1);
            if (exit)
                throw new Exception("手机号已使用");
            user.Tele = input;
            return await _userRepository.UpdateAsync(user);
        }

        /// <summary>
        /// 账号注销
        /// </summary>
        /// <returns></returns>
        public async Task<bool> AccountCancellation()
        {
            var user = await _userRepository.GetByIdAsync(_userContext.Id);
            user.State = -1;
            return await _userRepository.UpdateAsync(user);
        }

        /// <summary>
        /// 更新用户信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppResult> UpdateUserInforByWeChat(UserWechatDto input)
        {
            var response = await _weChatService.GetJsCode2Session(input.Code);
            if (!response.IsSuccessful())
                return new AppResult(400, response.ErrorMessage);
            var userinfo = EncryptHelper.DecodeEncryptedDataToEntityEasy<DecodedUserInfo>(response.SessionKey, input.EncryptedData, input.Iv);
            var user = await _userRepository.GetByIdAsync(_userContext.Id);
            user.Nickname = userinfo.nickName;
            user.Head = userinfo.avatarUrl;
            user.Sex = userinfo.gender;
            await _userRepository.UpdateAsync(user);
            return new AppResult();
        }


        public async Task<bool> UpdateUserHead(string input)
        {
            var user = await _userRepository.GetByIdAsync(_userContext.Id);
            user.Head = input;
            return await _userRepository.UpdateAsync(user);
        }


        /// <summary>
        /// 添加合同
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppResult> Contract(AddContractDto input)
        {
            try
            {
                var user = await _userRepository.GetByIdAsync(_userContext.Id);
                if (user.Audit != 1)
                    return new AppResult(404, "用户不满足条件");
                if (_userRepository.Change<UserContract>().IsAny(x => x.UserId == _userContext.Id && x.State == 0))
                    return new AppResult(404, "有多个未审核的合同");
                await _userRepository.Change<UserContract>().InsertAsync(new UserContract
                {
                    Code = CreateOrderCode(),
                    UserId = _userContext.Id,
                    Contract = input.Contract,
                    IDCard = input.IDCard,
                    IDCardBack = input.IDCardBack,
                });
                _userRepository.AsUpdateable().Where(x => x.Id == user.Id)
                .SetColumns(x => x.Audit == 2)
                .ExecuteCommand(); ;
                return new AppResult();
            }
            catch (Exception)
            {
                return new AppResult(404, "提交合同失败");
            }
        }

        public async Task<bool> UpdateUserName(string input)
        {
            var user = await _userRepository.GetByIdAsync(_userContext.Id);
            user.Nickname = input;
            return await _userRepository.UpdateAsync(user);
        }
        
        /// <summary>
        /// Code生成
        /// </summary>
        /// <returns></returns>
        private static string CreateOrderCode()
        {
            Random random = new Random();
            string strRandom = random.Next(10000, 99999).ToString();
            string code = $"DYFZK{DateTime.Now.ToString("yyyyMMddHHmmssffff")}{strRandom}";
            return code;
        }
    }
}
